package service

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"
)

// WindowsServiceManager Windows 服务管理器
type WindowsServiceManager struct {
	usePowerShell bool
}

// NewWindowsServiceManager 创建 Windows 服务管理器
func NewWindowsServiceManager() *WindowsServiceManager {
	return &WindowsServiceManager{
		usePowerShell: true, // 优先使用 PowerShell
	}
}

// Status 获取 Windows 服务状态
func (wsm *WindowsServiceManager) Status(serviceName string) (*ServiceInfo, error) {
	if wsm.usePowerShell {
		return wsm.getServiceStatusPowerShell(serviceName)
	}
	return wsm.getServiceStatusSC(serviceName)
}

// getServiceStatusPowerShell 使用 PowerShell 获取服务状态
func (wsm *WindowsServiceManager) getServiceStatusPowerShell(serviceName string) (*ServiceInfo, error) {
	// PowerShell 命令获取详细服务信息
	psCommand := fmt.Sprintf(`
        $service = Get-Service -Name "%s" -ErrorAction SilentlyContinue
        if ($service) {
            $service | Select-Object Name, DisplayName, Status, ServiceType, 
                @{Name="StartType"; Expression={$_.StartType}},
                @{Name="BinaryPath"; Expression={(Get-WmiObject Win32_Service -Filter "Name='$($_.Name)'").PathName}}
        } else {
            Write-Output "Service not found"
        }
    `, serviceName)

	cmd := exec.Command("powershell", "-Command", psCommand)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("failed to get service status: %v", err)
	}

	return wsm.parsePowerShellOutput(serviceName, string(output))
}

// getServiceStatusSC 使用 sc 命令获取服务状态
func (wsm *WindowsServiceManager) getServiceStatusSC(serviceName string) (*ServiceInfo, error) {
	cmd := exec.Command("sc", "query", serviceName)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("failed to query service: %v", err)
	}

	return wsm.parseSCOutput(serviceName, string(output))
}

// Start 启动 Windows 服务
func (wsm *WindowsServiceManager) Start(serviceName string) error {
	var cmd *exec.Cmd

	if wsm.usePowerShell {
		psCommand := fmt.Sprintf(`Start-Service -Name "%s"`, serviceName)
		cmd = exec.Command("powershell", "-Command", psCommand)
	} else {
		cmd = exec.Command("sc", "start", serviceName)
	}

	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to start service %s: %v, output: %s",
			serviceName, err, string(output))
	}

	return nil
}

// Stop 停止 Windows 服务
func (wsm *WindowsServiceManager) Stop(serviceName string) error {
	var cmd *exec.Cmd

	if wsm.usePowerShell {
		psCommand := fmt.Sprintf(`Stop-Service -Name "%s"`, serviceName)
		cmd = exec.Command("powershell", "-Command", psCommand)
	} else {
		cmd = exec.Command("sc", "stop", serviceName)
	}

	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to stop service %s: %v, output: %s",
			serviceName, err, string(output))
	}

	return nil
}

// Restart 重启 Windows 服务
func (wsm *WindowsServiceManager) Restart(serviceName string) error {
	var cmd *exec.Cmd

	if wsm.usePowerShell {
		psCommand := fmt.Sprintf(`Restart-Service -Name "%s"`, serviceName)
		cmd = exec.Command("powershell", "-Command", psCommand)
	} else {
		// sc 没有直接的 restart 命令，需要先停止再启动
		if err := wsm.Stop(serviceName); err != nil {
			return err
		}
		time.Sleep(2 * time.Second)
		return wsm.Start(serviceName)
	}

	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to restart service %s: %v, output: %s",
			serviceName, err, string(output))
	}

	return nil
}

// List 列出所有 Windows 服务
func (wsm *WindowsServiceManager) List() ([]ServiceInfo, error) {
	if wsm.usePowerShell {
		return wsm.listServicesPowerShell()
	}
	return wsm.listServicesSC()
}

// listServicesPowerShell 使用 PowerShell 列出服务
func (wsm *WindowsServiceManager) listServicesPowerShell() ([]ServiceInfo, error) {
	psCommand := `
        Get-Service | Select-Object Name, DisplayName, Status | 
        ConvertTo-Json -Compress
    `

	cmd := exec.Command("powershell", "-Command", psCommand)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("failed to list services: %v", err)
	}

	var services []map[string]interface{}
	if err := json.Unmarshal(output, &services); err != nil {
		return nil, fmt.Errorf("failed to parse services JSON: %v", err)
	}

	var result []ServiceInfo
	for _, svc := range services {
		service := ServiceInfo{
			Name:        getString(svc, "Name"),
			DisplayName: getString(svc, "DisplayName"),
			Status:      wsm.mapWindowsStatus(getString(svc, "Status")),
		}
		result = append(result, service)
	}

	return result, nil
}

// listServicesSC 使用 sc 命令列出服务
func (wsm *WindowsServiceManager) listServicesSC() ([]ServiceInfo, error) {
	cmd := exec.Command("sc", "query", "type=", "service", "state=", "all")
	output, err := cmd.CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("failed to list services: %v", err)
	}

	return wsm.parseSCListOutput(string(output))
}

// Logs 获取 Windows 服务日志
func (wsm *WindowsServiceManager) Logs(serviceName string, lines int) (string, error) {
	if !wsm.usePowerShell {
		return "Event logs require PowerShell", nil
	}

	psCommand := fmt.Sprintf(`
        Get-EventLog -LogName System -Source "Service Control Manager" | 
        Where-Object {$_.Message -like "*%s*"} | 
        Select-Object TimeGenerated, EntryType, Message -First %d |
        Format-Table -Wrap
    `, serviceName, lines)

	cmd := exec.Command("powershell", "-Command", psCommand)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return "", fmt.Errorf("failed to get service logs: %v", err)
	}

	return string(output), nil
}

// IsActive 检查服务是否运行
func (wsm *WindowsServiceManager) IsRunning(serviceName string) (bool, error) {
	status, err := wsm.Status(serviceName)
	if err != nil {
		return false, err
	}
	return status.Status == "running", nil
}

// Enable 启用 Windows 服务
func (wsm *WindowsServiceManager) Enable(serviceName string) error {
	var cmd *exec.Cmd

	if wsm.usePowerShell {
		psCommand := fmt.Sprintf(`Set-Service -Name "%s" -StartupType Automatic`, serviceName)
		cmd = exec.Command("powershell", "-Command", psCommand)
	} else {
		cmd = exec.Command("sc", "config", serviceName, "start=", "auto")
	}

	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to enable service %s: %v, output: %s",
			serviceName, err, string(output))
	}

	return nil
}

// Disable 禁用 Windows 服务
func (wsm *WindowsServiceManager) Disable(serviceName string) error {
	var cmd *exec.Cmd

	if wsm.usePowerShell {
		psCommand := fmt.Sprintf(`Set-Service -Name "%s" -StartupType Disabled`, serviceName)
		cmd = exec.Command("powershell", "-Command", psCommand)
	} else {
		cmd = exec.Command("sc", "config", serviceName, "start=", "disabled")
	}

	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to disable service %s: %v, output: %s",
			serviceName, err, string(output))
	}

	return nil
}

// parsePowerShellOutput 解析 PowerShell 输出
func (wsm *WindowsServiceManager) parsePowerShellOutput(serviceName, output string) (*ServiceInfo, error) {
	info := &ServiceInfo{Name: serviceName}

	lines := strings.Split(output, "\n")
	for _, line := range lines {
		line = strings.TrimSpace(line)

		if strings.Contains(line, "DisplayName") {
			re := regexp.MustCompile(`DisplayName\s*:\s*(.+)`)
			matches := re.FindStringSubmatch(line)
			if len(matches) == 2 {
				info.DisplayName = strings.TrimSpace(matches[1])
			}
		}

		if strings.Contains(line, "Status") {
			re := regexp.MustCompile(`Status\s*:\s*(\w+)`)
			matches := re.FindStringSubmatch(line)
			if len(matches) == 2 {
				info.Status = wsm.mapWindowsStatus(strings.TrimSpace(matches[1]))
				info.State = strings.TrimSpace(matches[1])
			}
		}

		if strings.Contains(line, "StartType") {
			re := regexp.MustCompile(`StartType\s*:\s*(\w+)`)
			matches := re.FindStringSubmatch(line)
			if len(matches) == 2 {
				info.StartType = strings.TrimSpace(matches[1])
			}
		}

		if strings.Contains(line, "BinaryPath") {
			re := regexp.MustCompile(`BinaryPath\s*:\s*(.+)`)
			matches := re.FindStringSubmatch(line)
			if len(matches) == 2 {
				info.BinaryPath = strings.TrimSpace(matches[1])
			}
		}
	}

	return info, nil
}

// parseSCOutput 解析 sc query 输出
func (wsm *WindowsServiceManager) parseSCOutput(serviceName, output string) (*ServiceInfo, error) {
	info := &ServiceInfo{Name: serviceName}

	lines := strings.Split(output, "\n")
	for _, line := range lines {
		line = strings.TrimSpace(line)

		if strings.HasPrefix(line, "DISPLAY_NAME") {
			parts := strings.SplitN(line, ":", 2)
			if len(parts) == 2 {
				info.DisplayName = strings.TrimSpace(parts[1])
			}
		}

		if strings.HasPrefix(line, "STATE") {
			re := regexp.MustCompile(`STATE\s*:\s*(\d+)\s+(\w+)`)
			matches := re.FindStringSubmatch(line)
			if len(matches) == 3 {
				info.Status = wsm.mapWindowsStatus(matches[2])
				info.State = matches[2]
			}
		}

		if strings.HasPrefix(line, "PID") {
			re := regexp.MustCompile(`PID\s*:\s*(\d+)`)
			matches := re.FindStringSubmatch(line)
			if len(matches) == 2 {
				pid, _ := strconv.Atoi(matches[1])
				info.PID = pid
			}
		}
	}

	return info, nil
}

// parseSCListOutput 解析 sc query 列表输出
func (wsm *WindowsServiceManager) parseSCListOutput(output string) ([]ServiceInfo, error) {
	var services []ServiceInfo
	var currentService *ServiceInfo

	scanner := bufio.NewScanner(bytes.NewReader([]byte(output)))
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())

		if strings.HasPrefix(line, "SERVICE_NAME:") {
			if currentService != nil {
				services = append(services, *currentService)
			}
			parts := strings.SplitN(line, ":", 2)
			if len(parts) == 2 {
				currentService = &ServiceInfo{Name: strings.TrimSpace(parts[1])}
			}
		}

		if currentService != nil {
			if strings.HasPrefix(line, "DISPLAY_NAME") {
				parts := strings.SplitN(line, ":", 2)
				if len(parts) == 2 {
					currentService.DisplayName = strings.TrimSpace(parts[1])
				}
			}

			if strings.HasPrefix(line, "STATE") {
				re := regexp.MustCompile(`STATE\s*:\s*(\d+)\s+(\w+)`)
				matches := re.FindStringSubmatch(line)
				if len(matches) == 3 {
					currentService.Status = wsm.mapWindowsStatus(matches[2])
					currentService.State = matches[2]
				}
			}
		}
	}

	if currentService != nil {
		services = append(services, *currentService)
	}

	return services, nil
}

// mapWindowsStatus 映射 Windows 服务状态
func (wsm *WindowsServiceManager) mapWindowsStatus(windowsStatus string) string {
	switch strings.ToLower(windowsStatus) {
	case "running", "started", "run":
		return "running"
	case "stopped", "stop":
		return "stopped"
	case "paused", "pause":
		return "paused"
	case "starting", "start_pending":
		return "starting"
	case "stopping", "stop_pending":
		return "stopping"
	default:
		return windowsStatus
	}
}

// getString 从 map 中安全获取字符串
func getString(m map[string]interface{}, key string) string {
	if val, ok := m[key]; ok {
		if str, ok := val.(string); ok {
			return str
		}
	}
	return ""
}
